#    pythonequations is a collection of equations expressed as Python classes
#    Copyright (C) 2008 James R. Phillips
#    2548 Vera Cruz Drive
#    Birmingham, AL 35235 USA
#    email: zunzun@zunzun.com
#
#    License: BSD-style (see LICENSE.txt in main source directory)
#    Version info: $Id: Optical.py 274 2010-09-29 13:16:14Z zunzun.com $

import pythonequations, pythonequations.EquationBaseClasses, pythonequations.ExtraCodeForEquationBaseClasses
import numpy
numpy.seterr(all = 'raise') # numpy raises warnings, convert to exceptions to trap them


class SagForAsphere03D(pythonequations.EquationBaseClasses.Equation3D):
    RequiresAutoGeneratedGrowthAndDecayForms = True
    RequiresAutoGeneratedOffsetForm = False
    RequiresAutoGeneratedReciprocalForm = False
    RequiresAutoGeneratedInverseForms = False
    _name ="Sag For Asphere 0"
    _HTML = "s<SUP>2</SUP> = x<SUP>2</SUP> + y<SUP>2</SUP><BR>z = (s<SUP>2</SUP>/r) / (1+(1-(k+1)(s/r)<SUP>2</SUP>)<SUP>1/2</SUP>) + offset"
    coefficientDesignatorTuple = ("k", "r", "offset")
    function_cpp_code = 's_sq = _id[_cwo[0]+i] * _id[_cwo[0]+i] + _id[_cwo[1]+i] * _id[_cwo[1]+i];\n'
    function_cpp_code += 's_over_r = pow(s_sq, 0.5) / coeff[1];\n'
    function_cpp_code += 'temp = (s_sq / coeff[1]) / (1.0 + pow(1.0 - (coeff[0] + 1.0) * s_over_r * s_over_r, 0.5)) + coeff[2];'


    def CreateCacheGenerationList(self):
        self.CacheGenerationList = []
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_X(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Y(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Ones(NameOrValueFlag=1), []])

    def SpecificCodeCPP(self):
        s = ""
        j = self.coefficientDesignatorTuple # makes coding below easier to read
        s += '\tdouble s_sq = x_in * x_in + y_in * y_in;\n'
        s += '\tdouble s_over_r = pow(s_sq, 0.5) / ' + j[1] + ';\n'
        s += '\ttemp = (s_sq / ' + j[1] + ') / (1.0 + pow(1.0 - (' + j[0] + ' + 1.0) * s_over_r * s_over_r, 0.5)) + ' + j[2] + ';\n'
        return s



class SagForAsphere0_Borisovsky_3D(pythonequations.EquationBaseClasses.Equation3D):
    RequiresAutoGeneratedGrowthAndDecayForms = True
    RequiresAutoGeneratedOffsetForm = False
    RequiresAutoGeneratedReciprocalForm = False
    RequiresAutoGeneratedInverseForms = False
    _name ="Sag For Asphere 0 Borisovsky"
    _HTML = "s<SUP>2</SUP> = (x - a)<SUP>2</SUP> + (y - b)<SUP>2</SUP><BR>z = (s<SUP>2</SUP>/r) / "
    _HTML += "(1+(1-(k+1)(s/r)<SUP>2</SUP>)<SUP>1/2</SUP>) + offset"
    coefficientDesignatorTuple = ("a", "b", "k", "r", "offset")
    function_cpp_code = 's_sq_b = ((_id[_cwo[0]+i] - coeff[0]) * (_id[_cwo[0]+i] - coeff[0])) + '
    function_cpp_code += '((_id[_cwo[1]+i] - coeff[1]) * (_id[_cwo[1]+i] - coeff[1]));\n'
    function_cpp_code += 's_over_r_b = pow(s_sq_b, 0.5) / coeff[3];\n'
    function_cpp_code += 'temp = (s_sq_b/ coeff[3]) / (1.0 + pow(1.0 - (coeff[2] + 1.0) * s_over_r_b * s_over_r_b, 0.5)) + coeff[4];'


    def CreateCacheGenerationList(self):
        self.CacheGenerationList = []
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_X(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Y(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Ones(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Ones(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Ones(NameOrValueFlag=1), []])

    def SpecificCodeCPP(self):
        s = ""
        j = self.coefficientDesignatorTuple # makes coding below easier to read

        s += '\tdouble s_sq = (x_in - ' + j[0] + ') * (x_in - ' + j[0] + ') + (y_in - ' + j[1] + ') * (y_in - ' + j[1] + ');\n'
        s += '\tdouble s_over_r = pow(s_sq, 0.5) / ' + j[1] + ';\n'
        s += '\ttemp = (s_sq / ' + j[3] + ') / (1.0 + pow(1.0 - (' + j[2] + ' + 1.0) * s_over_r * s_over_r, 0.5)) + ' + j[4] + ';\n'
        return s
